home *** CD-ROM | disk | FTP | other *** search
/ A.C.E. 2 / ACE CD 2.iso / FILES / UTILS / GAMESDS3.DMS / GAMESDS3.adf / GDS_Examples.lha / Examples / bubble / bubble_copper.c < prev    next >
C/C++ Source or Header  |  1994-11-14  |  21KB  |  651 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <exec/memory.h>
  5. #include <exec/types.h>
  6. #include <graphics/gfx.h>
  7. #include <graphics/gfxbase.h>
  8.  
  9. #include <proto/exec.h>
  10. #include <proto/graphics.h>
  11.  
  12. #include "GameSmith:GameSmith.h"
  13. #include "GameSmith:include/libraries/libptrs.h"
  14. #include "bubble.h"
  15.  
  16. /*-------------------------------------------------------------------------*/
  17. /* Function Prototypes                                                      */
  18.  
  19. void parser(int,char **);
  20. int setup(void);
  21. void color_cycle(void);
  22. void build_copper(struct anim_load_struct *);
  23. void move_image(void);
  24. void check_bounds(void);
  25. __stdargs void collision(struct anim_struct *,struct anim_struct *,
  26.      struct collision_struct *,struct collision_struct *);
  27. int check_close(void);
  28. void cleanup(void);
  29. void free_arrays(void);
  30.  
  31. /*-------------------------------------------------------------------------*/
  32. /* some global variables                                                   */
  33.  
  34. int bubble_cnt,swidth,sheight,smode,delay=0,random_x=11,random_y=9;
  35. int *x=NULL,*y=NULL,*speedx=NULL,*speedy=NULL,*reset=NULL,*last=NULL;
  36. int dlist;                        /* display list handle for anims */
  37.  
  38. int break_offset=-1,palette_size;
  39. int copheight;                     /* height of copper screen */
  40. short red,green,blue;            /* background copper colors */
  41. unsigned short chipset;            /* chiset version */
  42.  
  43. struct BitMap *bm3=NULL;
  44.  
  45. struct anim_struct *bubble;
  46.  
  47. struct Interrupt *cycle=NULL;
  48.  
  49. /*-------------------------------------------------------------------------*/
  50.  
  51. unsigned short copper_list[4096];   /* enough for our custom user copper list */
  52.  
  53. struct gs_viewport vp =
  54.    {
  55.    NULL,                           /* ptr to next viewport */
  56.    NULL,                           /* ptr to color table */
  57.    0,                              /* number of colors in table */
  58.    NULL,                           /* ptr to user copper list (none yet) */
  59.    0,0,0,0,0,                     /* height, width, depth, bmheight, bmwidth */
  60.    0,0,                           /* top & left viewport offsets */
  61.    0,0,                           /* X & Y bitmap offsets */
  62.    GSVP_ALLOCBM|GSVP_NOCOLOR|GSVP_NOWAIT,   /* flags */
  63.    NULL,NULL,                     /* 2.xx & above compatibility stuff */
  64.    NULL,NULL,                     /* bitmap pointers */
  65.    NULL,                           /* future expansion */
  66.    0,0,0,0                        /* display clip (use nominal) */
  67.    };
  68.  
  69. struct display_struct bubble_display =
  70.    {
  71.    NULL,                           /* ptr to previous display view */
  72.    NULL,NULL,                     /* 2.xx & above compatibility stuff */
  73.    0,0,                           /* X and Y display offsets */
  74.    0,                              /* display mode ID */
  75.    4,4,                           /* sprite priorities (sprites in front of playfields) */
  76.    GSV_DOUBLE,                     /* flags */
  77.    &vp,                           /* ptr to 1st viewport */
  78.    NULL                           /* future expansion */
  79.    };
  80.  
  81. struct hard_copper hc =
  82.    {
  83.    &bubble_display,               /* addr of target display */
  84.    copper_list,                  /* addr of pnemonic copper list */
  85.    UCF_DOUBLE,                     /* flags (double buffered display) */
  86.    };
  87.  
  88. /***************************************************************************/
  89.  
  90. main(argc,argv)
  91. int argc;
  92. char *argv[];
  93.  
  94. {
  95.    int err,end=0;
  96.  
  97.    if (argc < 2)
  98.       {
  99.       printf("\nUSAGE: bubbles [number of bubbles] [HIRES] [SUPER] [VB delay intervals] [X speed] [Y speed]\n");
  100.       exit(01);
  101.       }
  102.    if (gs_open_libs(DOS|GRAPHICS,0))   /* open AmigaDOS libs */
  103.       exit(01);               /* if can't open libs, abort */
  104.    parser(argc,argv);         /* parse command line args */
  105.    chipset=gs_chiprev();      /* find out what machine we're running on */
  106.    if (err=setup())            /* if couldn't get set up... abort program */
  107.       {
  108.       printf("\nSetup error: %d\n",err);
  109.       gs_close_libs();         /* close all libraries */
  110.       exit(02);
  111.       }
  112.    cycle=gs_add_vb_server(&color_cycle,0); /* add color cycle to vertical blank server chain */
  113.    if (!cycle)
  114.       {
  115.       cleanup();                  /* close & deallocate everything */
  116.       printf("\nUnable to add vertical blank server\n");
  117.       gs_close_libs();         /* close all libraries */
  118.       exit(03);
  119.       }
  120.    Forbid();                  /* take over the entire machine */
  121.    while (!end)               /* this shows off speed */
  122.       {
  123.       move_image();            /* move them bubbles around */
  124.       end=check_close();      /* end when user hits left mouse button */
  125.       }
  126.    Permit();                  /* OK, let other things run while we clean up */
  127.    cleanup();                  /* close & deallocate everything */
  128.    gs_close_libs();            /* close all libraries */
  129. }
  130.  
  131. /***************************************************************************/
  132.  
  133. void parser(argc,argv)
  134. int argc;
  135. char *argv[];
  136.  
  137. {
  138.    bubble_cnt=atoi(argv[1]);   /* # anims to place on the screen */
  139.    swidth=320;                  /* default width & height */
  140.    sheight=200;
  141.    copheight=200;
  142.    smode=0;                     /* default mode of lores no lace */
  143.    #ifdef NTSC_MONITOR_ID
  144.       if (GfxBase->LibNode.lib_Version >= 36)   /* if WB 2.0 or higher */
  145.          {               /* this defeats mode promotion on AGA machines */
  146.          if (ModeNotAvailable(NTSC_MONITOR_ID))
  147.             {
  148.             smode = PAL_MONITOR_ID;
  149.             sheight=256;
  150.             copheight=256;
  151.             }
  152.          else
  153.             {
  154.             smode = NTSC_MONITOR_ID;
  155.             }
  156.          }
  157.    #endif
  158.    if (argc >= 3)
  159.       {
  160.       if (!(stricmp(argv[2],"DBL")))   /* check for double scan */
  161.          {
  162.          #ifdef DBLNTSC_MONITOR_ID
  163.          if (GfxBase->LibNode.lib_Version >= 39)   /* if WB 3.0 or higher */
  164.             {               /* try for mode promoted AGA display */
  165.             if (!ModeNotAvailable(DBLNTSC_MONITOR_ID))
  166.                {
  167.                smode = DBLNTSC_MONITOR_ID;
  168.                copheight=400;
  169.                }
  170.             else if (!ModeNotAvailable(DBLPAL_MONITOR_ID))
  171.                {
  172.                smode = DBLPAL_MONITOR_ID;
  173.                sheight=256;
  174.                copheight=512;
  175.                }
  176.             }
  177.          #endif
  178.          }
  179.       else if (!(stricmp(argv[2],"DBLHIRES")))   /* check for hires double scan */
  180.          {
  181.          #ifdef DBLNTSC_MONITOR_ID
  182.          if (GfxBase->LibNode.lib_Version >= 39)   /* if WB 3.0 or higher */
  183.             {               /* try for mode promoted AGA display */
  184.             if (!ModeNotAvailable(DBLNTSC_MONITOR_ID))
  185.                {
  186.                swidth=640;
  187.                smode = DBLNTSC_MONITOR_ID;
  188.                copheight=400;
  189.                sheight=400;
  190.                }
  191.             else if (!ModeNotAvailable(DBLPAL_MONITOR_ID))
  192.                {
  193.                swidth=640;
  194.                smode = DBLPAL_MONITOR_ID;
  195.                sheight=256;
  196.                copheight=512;
  197.                }
  198.             smode|=HIRES|LACE;
  199.             }
  200.          #endif
  201.          }
  202.       else if (!(stricmp(argv[2],"HIRES")))   /* check for hires spec */
  203.          {
  204.          swidth=640;
  205.          sheight=400;
  206.          smode|=HIRES|LACE;
  207.          }
  208.       else if (!(stricmp(argv[2],"SUPER")))   /* check for superhires72 */
  209.          {
  210.          #ifdef SUPER72_MONITOR_ID
  211.          if (GfxBase->LibNode.lib_Version >= 36)
  212.             {
  213.             if (!ModeNotAvailable(SUPER72_MONITOR_ID | SUPERLACE_KEY))
  214.                {
  215.                smode=SUPER72_MONITOR_ID | SUPERLACE_KEY;
  216.                swidth=800;
  217.                sheight=600;
  218.                copheight=300;
  219.                }
  220.             }
  221.          #endif
  222.          }
  223.       }
  224.    if (argc >= 4)
  225.       {
  226.       delay=atoi(argv[3]);      /* delay value in vertical blank intervals */
  227.       }
  228.    if (argc >= 5)               /* new random X speed range */
  229.       {
  230.       random_x=atoi(argv[4]);
  231.       if (random_x < 2)
  232.          random_x=2;
  233.       }
  234.    if (argc >= 6)               /* new random Y speed range */
  235.       {
  236.       random_y=atoi(argv[5]);
  237.       if (random_y < 2)
  238.          random_y=2;
  239.       }
  240. }
  241.  
  242. /***************************************************************************/
  243.  
  244. int setup()
  245.  
  246. {
  247.    int cnt,depth=0;
  248.    struct blit_struct *img;
  249.    struct anim_load_struct load;
  250.  
  251.    if (!(x=(int *)malloc(bubble_cnt*sizeof(int))))
  252.       return(-1);
  253.    if (!(y=(int *)malloc(bubble_cnt*sizeof(int))))
  254.       {
  255.       free_arrays();
  256.       return(-1);
  257.       }
  258.    if (!(speedx=(int *)malloc(bubble_cnt*sizeof(int))))
  259.       {
  260.       free_arrays();
  261.       return(-1);
  262.       }
  263.    if (!(speedy=(int *)malloc(bubble_cnt*sizeof(int))))
  264.       {
  265.       free_arrays();
  266.       return(-1);
  267.       }
  268.    if (!(last=(int *)malloc(bubble_cnt*sizeof(int))))
  269.       {
  270.       free_arrays();
  271.       return(-1);
  272.       }
  273.    if (!(reset=(int *)malloc(bubble_cnt*sizeof(int))))
  274.       {
  275.       free_arrays();
  276.       return(-1);
  277.       }
  278.    load.filename="bubble";            /* name of anim file */
  279.    load.cmap_size=8;                  /* number of bits per color value */
  280.    load.array_elements=bubble_cnt;   /* number of array elements desired */
  281.    load.flags=0L;                     /* no special load flags */
  282.    if (gs_load_anim(&load))         /* load the anim object */
  283.       {
  284.       free_arrays();
  285.       return(-1);
  286.       }
  287.    bubble=load.anim_ptr.anim;         /* ptr to bubble anim */
  288.    if (load.type)                     /* make sure it's an anim type */
  289.       {
  290.       FreeMem(load.cmap,load.cmap_entries*sizeof(long));
  291.       free_arrays();
  292.       if (load.type = 1)
  293.          gs_free_cplx((struct anim_cplx *)bubble,bubble_cnt);
  294.       return(-2);
  295.       }
  296.    img = bubble[0].list;            /* ptr to 1st image in anim sequence */
  297.    while (img)                        /* find max depth of anim */
  298.       {
  299.       if (img->depth > depth)
  300.          depth = img->depth;
  301.       if (img->next == img)         /* avoid infinite loop */
  302.          img=NULL;                  /* if single shot anim */
  303.       else
  304.          img=img->next;
  305.       }
  306.    vp.height = sheight;               /* set up display dimensions */
  307.    vp.width = swidth;
  308.    vp.depth = depth;
  309.    vp.bmheight = sheight;
  310.    vp.bmwidth = swidth;
  311.    bubble_display.modes = smode;
  312.    if (gs_create_display(&bubble_display))
  313.       {
  314.       FreeMem(load.cmap,load.cmap_entries*sizeof(long));
  315.       free_arrays();
  316.       gs_free_anim(bubble,bubble_cnt);
  317.       return(-2);
  318.       }
  319.    build_copper(&load);                     /* build custom copper list */
  320.    FreeMem(load.cmap,load.cmap_entries*sizeof(long));   /* done with color table */
  321.    if ((dlist=gs_get_display_list()) < 0)   /* allocate a display list for anims */
  322.       {
  323.       free_arrays();
  324.       gs_free_anim(bubble,bubble_cnt);
  325.       return(-3);
  326.       }
  327.    bm3=gs_get_bitmap(vp.depth,vp.bmwidth,vp.bmheight,0);
  328.    gs_init_anim(dlist,vp.bitmap1,vp.bitmap2,bm3);   /* tell anim system about bitmaps */
  329.    gs_set_anim_bounds(dlist,0,0,swidth-1,sheight-1);   /* set bounds for anim objects */
  330.    gs_set_collision(dlist,&collision);   /* set ptr to collision handler */
  331.    for (cnt=0; cnt < bubble_cnt; cnt++)
  332.       {                              /* add all bubbles to a display list */
  333.       reset[cnt]=0;
  334.       last[cnt]=-1;
  335.       x[cnt] = gs_random(swidth);   /* random X,Y coords */
  336.       y[cnt] = gs_random(sheight);
  337.       while ((speedx[cnt] = gs_random(random_x)) == 0);
  338.       while ((speedy[cnt] = gs_random(random_y)) == 0);
  339.       if (cnt&1)
  340.          {
  341.          speedx[cnt]*=-1;
  342.          speedy[cnt]*=-1;
  343.          }
  344.       if (bm3)                        /* if restore bitmap */
  345.          {
  346.          bubble[cnt].flags|=ANIM_SAVE_BG;   /* use fastest display method (next to simple copy) */
  347.          if (bubble[cnt].flags & ANIM_CLEAR)
  348.             bubble[cnt].flags ^= ANIM_CLEAR;
  349.          if (bubble[cnt].flags & ANIM_COPY)
  350.             bubble[cnt].flags ^= ANIM_COPY;
  351.          }
  352.       if (gs_add_anim(dlist,(struct anim_struct *)&bubble[cnt],x[cnt],y[cnt]))
  353.          {
  354.          cleanup();                  /* release everything */
  355.          return(-4);                  /* return failure */
  356.          }
  357.       gs_set_anim_cell((struct anim_struct *)&bubble[cnt],gs_random(bubble[cnt].count));
  358.       }
  359.    gs_draw_anims(dlist);
  360.    check_bounds();
  361.    gs_next_anim_page(dlist);
  362.    gs_show_display(&bubble_display,1);
  363.    gs_flip_display(&bubble_display,1);
  364.    gs_open_vb_timer();
  365.    return(0);
  366. }
  367.  
  368. /***************************************************************************/
  369.  
  370. void __interrupt __saveds color_cycle()
  371.  
  372. {
  373. /* THIS IS THE ULTRA SPEEDY WAY TO UPDATE THE COPPER LIST!  RIGHT TO THE HARDWARE! */
  374. /* We'll put this routine in the vertical blank for automatic color cycling.       */
  375.  
  376.    static int cnt=0,cnt3=0,cnt2=0;
  377.    unsigned short rgb_high,rgb_low;
  378.    static unsigned short *cop1=NULL,*cop2,*cop3,*cop4;
  379.  
  380.    if (!cop1)         /* if 1st time */
  381.       {
  382.       cop1=vp.LOF_ucop1+palette_size+1;   /* remember, these are WORD pointers */
  383.       cop4=cop3=cop2=cop1;
  384.       if (vp.SHF_ucop1)
  385.          cop2=vp.SHF_ucop1+palette_size+1;
  386.       if (vp.LOF_ucop2)
  387.          cop3=vp.LOF_ucop2+palette_size+1;
  388.       if (vp.SHF_ucop2)
  389.          cop4=vp.SHF_ucop2+palette_size+1;
  390.       if (chipset == AGA_CHIPREV)
  391.          {
  392.          cop1+=2;
  393.          cop2+=2;
  394.          cop3+=2;
  395.          cop4+=2;
  396.          }
  397.       }
  398.    rgb_high=((red&0xf0)<<4)|(green&0xf0)|((blue&0xf0)>>4);
  399.    rgb_low=((red&0x0f)<<8)|((green&0x0f)<<4)|(blue&0x0f);
  400.    red++;
  401.    green++;
  402.    blue++;
  403.    if ((red > 255) || (green > 255) || (blue > 255))
  404.       {
  405.       red=gs_random(128);         /* random starting colors */
  406.       green=gs_random(128);
  407.       blue=gs_random(128);
  408.       }
  409.    if (cnt3 == break_offset)      /* skip wait break-over point for copper */
  410.       {
  411.       cnt2+=2;                     /* this gets past line 256 (copper vertical res = 8 bit) */
  412.       }                           /* now modify hardware list directly */
  413.    cop1[cnt2]=rgb_high;            /* set high order color bits */
  414.    cop2[cnt2]=rgb_high;
  415.    cop3[cnt2]=rgb_high;
  416.    cop4[cnt2]=rgb_high;
  417.    cnt2+=4;                        /* skip over bank/low-order select */
  418.    if (chipset == AGA_CHIPREV)
  419.       {
  420.       cop1[cnt2]=rgb_low;         /* set low order color bits */
  421.       cop2[cnt2]=rgb_low;
  422.       cop3[cnt2]=rgb_low;
  423.       cop4[cnt2]=rgb_low;
  424.       cnt2+=6;                     /* skip over next wait and bank/high-order select */
  425.       }
  426.    cnt++;
  427.    cnt3++;
  428.    if (cnt >= copheight)         /* if reached end of list, start over */
  429.       {
  430.       cnt=cnt2=cnt3=0;
  431.       }
  432. }
  433.  
  434. /***************************************************************************/
  435.  
  436. void build_copper(load)
  437. struct anim_load_struct *load;
  438.  
  439. /* build a custom copper list of background color changes */
  440.  
  441. {
  442.    int cnt,cnt2=0,copbreak=0;
  443.  
  444.    for (cnt=1; cnt < load->cmap_entries; cnt++)   /* set color table except color 0 */
  445.       {
  446.       if (chipset == AGA_CHIPREV)
  447.          {
  448.          copper_list[cnt2++]=UC_SETCOLORAGA;   /* set AGA color register */
  449.          copper_list[cnt2++]=cnt;            /* register number */
  450.          copper_list[cnt2++]=(load->cmap[cnt]>>16)&0xff;      /* red color value */
  451.          copper_list[cnt2++]=(load->cmap[cnt]>>8)&0xff;      /* green color value */
  452.          copper_list[cnt2++]=load->cmap[cnt]&0xff;            /* blue color value */
  453.          }
  454.       else
  455.          {
  456.          copper_list[cnt2++]=UC_SETCOLOR;   /* set color register */
  457.          copper_list[cnt2++]=cnt;         /* register number */
  458.          copper_list[cnt2++]=((load->cmap[cnt]>>12)&0x0f00)|
  459.             ((load->cmap[cnt]>>8)&0xf0)|((load->cmap[cnt]>>4)&0x0f);
  460.          }
  461.       }
  462.    if (chipset == AGA_CHIPREV)
  463.       palette_size=(load->cmap_entries-1)*8;   /* remember how many words to skip */
  464.    else
  465.       palette_size=(load->cmap_entries-1)*2;   /* remember how many words to skip */
  466.    red=gs_random(128);                     /* random initial colors */
  467.    green=gs_random(128);
  468.    blue=gs_random(128);
  469.    for (cnt=0; cnt < copheight; cnt++)      /* build copper list */
  470.       {
  471.       if (cnt)
  472.          {
  473.          copper_list[cnt2++]=UC_WAIT;      /* copper wait instruction */
  474.          copper_list[cnt2++]=cnt;         /* y coord to wait on */
  475.          copper_list[cnt2++]=0;            /* x coord to wait on */
  476.          }
  477.       if (chipset == AGA_CHIPREV)
  478.          {
  479.          copper_list[cnt2++]=UC_SETCOLORAGA;   /* set AGA color register */
  480.          copper_list[cnt2++]=0;               /* register number */
  481.          copper_list[cnt2++]=red++;            /* red color value */
  482.          copper_list[cnt2++]=green++;         /* green color value */
  483.          copper_list[cnt2++]=blue++;         /* blue color value */
  484.          }
  485.       else
  486.          {
  487.          copper_list[cnt2++]=UC_SETCOLOR;   /* set color register */
  488.          copper_list[cnt2++]=0;            /* register number */
  489.          copper_list[cnt2++]=((red++<<4)&0x0f00)|
  490.             (green++&0xf0)|((blue++>>4)&0x0f);
  491.          }
  492.       if ((red > 255) || (green > 255) || (blue > 255))
  493.          {
  494.          red=gs_random(128);         /* random starting colors */
  495.          green=gs_random(128);
  496.          blue=gs_random(128);
  497.          }
  498.       if (((cnt+bubble_display.LOF_top) >= 256) && (!copbreak))
  499.          {
  500.          break_offset=cnt;   /* remember when we pass copper line 256 (hardware limitation) */
  501.          copbreak=1;
  502.          }
  503.       }
  504.    copper_list[cnt2++]=UC_END;            /* end coppper list */
  505.    if (gs_hard_copper(&hc,&vp))
  506.       return;
  507.    gs_replace_ucop(&bubble_display,&vp,&hc);
  508.    gs_free_hard_copper(&hc);
  509. }
  510. /***************************************************************************/
  511.  
  512. void move_image()
  513.  
  514. /* move and animate the graphic objects on the screen */
  515.  
  516. {
  517.    int cnt;
  518.  
  519.    if (gs_vb_time() < delay)
  520.       return;
  521.    gs_vb_timer_reset();
  522.    for (cnt=0; cnt < bubble_cnt; cnt++)
  523.       {
  524.       x[cnt]+=speedx[cnt];            /* move the object */
  525.       y[cnt]+=speedy[cnt];
  526.       gs_anim_obj((struct anim_struct *)&bubble[cnt],x[cnt],y[cnt]);
  527.       if (reset[cnt])               /* since anim doesn't loop, must reset */
  528.          {                           /* the sequence in the event of collision */
  529.          reset[cnt]=0;               /* start at 1st cell in anim sequence */
  530.          gs_set_anim_cell((struct anim_struct *)&bubble[cnt],0);
  531.          }
  532.       if (!bubble[cnt].collide)      /* if not colliding, clear last ptr */
  533.          last[cnt]=-1;
  534.       }
  535.    while (bubble_display.flags & GSV_FLIP);   /* while page not flipped yet */
  536.    gs_draw_anims(dlist);            /* draw them anim objects! */
  537.    check_bounds();                  /* bounce off of outer bitmap bounds */
  538.    gs_next_anim_page(dlist);         /* tell anim sys to use other bitmap */
  539.    gs_flip_display(&bubble_display,1);   /* switch to other display, sync */
  540. }
  541.  
  542. /***************************************************************************/
  543.  
  544. void check_bounds()
  545.  
  546. {
  547.    int cnt;
  548.  
  549.    for (cnt=0; cnt < bubble_cnt; cnt++)
  550.       {
  551.       if (bubble[cnt].flags & (ANIM_BOUNDS_X1|ANIM_BOUNDS_X2))
  552.          {
  553.          x[cnt]=bubble[cnt].x;   /* keep track of current location */
  554.          speedx[cnt]=-speedx[cnt];   /* reverse X direction */
  555.          reset[cnt]=1;            /* make bubble warp */
  556.          last[cnt]=-1;            /* no colliding */
  557.          }
  558.       if (bubble[cnt].flags & (ANIM_BOUNDS_Y1|ANIM_BOUNDS_Y2))
  559.          {
  560.          y[cnt]=bubble[cnt].y;
  561.          speedy[cnt]=-speedy[cnt];   /* reverse Y direction */
  562.          reset[cnt]=1;
  563.          last[cnt]=-1;
  564.          }
  565.       }
  566. }
  567.  
  568. /***************************************************************************/
  569.  
  570. int check_close()
  571.  
  572. /* check for user input */
  573.  
  574. {
  575.    if (gs_joystick(0) & (JOY_BUTTON1|JOY_BUTTON2))
  576.       return(1);
  577.    return(0);
  578. }
  579.  
  580. /***************************************************************************/
  581.  
  582. __stdargs void collision(anim1,anim2,coll1,coll2)
  583. struct anim_struct *anim1;
  584. struct anim_struct *anim2;
  585. struct collision_struct *coll1;
  586. struct collision_struct *coll2;
  587.  
  588. /*
  589.  
  590. This is the collision handler which makes the bubbles "bounce" off of
  591. each other.
  592.  
  593. */
  594.  
  595. {
  596.    int temp;
  597.  
  598.    if (last[anim1->array_num] != anim2->array_num)      /* if not same object */
  599.       {
  600.       last[anim1->array_num] = anim2->array_num;      /* remember last collision */
  601.       last[anim2->array_num] = anim1->array_num;
  602.       reset[anim1->array_num]=1;                        /* reset anim cell */
  603.       reset[anim2->array_num]=1;
  604.       temp=speedy[anim2->array_num];                  /* swap values */
  605.       speedy[anim2->array_num]=speedy[anim1->array_num];
  606.       speedy[anim1->array_num]=temp;
  607.       temp=speedx[anim2->array_num];
  608.       speedx[anim2->array_num]=speedx[anim1->array_num];
  609.       speedx[anim1->array_num]=temp;
  610.       }
  611. }
  612.  
  613. /***************************************************************************/
  614.  
  615. void cleanup()
  616.  
  617. /* release all resources and memory */
  618.  
  619. {
  620.    if (cycle)
  621.       gs_remove_vb_server(cycle);
  622.    free_arrays();
  623.    gs_free_anim(bubble,bubble_cnt);
  624.    gs_remove_display(&bubble_display);
  625.    gs_free_display_list(dlist);
  626.    gs_close_vb_timer();
  627. }
  628.  
  629. /***************************************************************************/
  630.  
  631. void free_arrays()
  632.  
  633. /* release memory used by control arrays */
  634.  
  635. {
  636.    if (x)
  637.       free(x);
  638.    if (y)
  639.       free(y);
  640.    if (speedx)
  641.       free(speedx);
  642.    if (speedy)
  643.       free(speedy);
  644.    if (last)
  645.       free(last);
  646.    if (reset)
  647.       free(reset);
  648.    if (bm3)
  649.       gs_free_bitmap(bm3);
  650. }
  651.